package vo
{
	import com.adobe.crypto.WSSEUsernameToken;
	import com.adobe.serialization.json.JSON;
	
	import flash.display.Bitmap;
	import flash.events.Event;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.net.SharedObject;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	
	import mx.collections.ArrayCollection;
	import mx.collections.Sort;
	import mx.collections.SortField;
	import mx.formatters.DateFormatter;
	
	public class WalkingVO
	{
		private static const URL_GRAPH_HATENA:String = "http://graph.hatena.ne.jp/";
		private static const URL_GRAPH_HATENA_API:String = "http://graph.hatena.ne.jp/api/data";
		private static const DB:String = "walking";
		
		private var hatenaDateFormatter:DateFormatter;

		private var walkingSO:SharedObject;

		private var isStandAlone:Boolean;
		private var userVO:UserVO;
		private var wsseToken:String;
		
		[Bindable]
		public var walkingData:ArrayCollection;
		
		[Bindable]
		public var succeededAuth:Boolean;
		
		[Bindable]
		public var graphImage:Bitmap;
		
		public function WalkingVO() {
			trace("WalkingVO.WalkingVO");
			hatenaDateFormatter = new DateFormatter();
			hatenaDateFormatter.formatString = "YYYY-MM-DD";
			
			walkingSO = SharedObject.getLocal("WalkingVO");

			isStandAlone = false;
			succeededAuth = false;
			setUserVO(new UserVO());
			
		}
		
		public function getIsStandAlone():Boolean {
			return this.isStandAlone;
		}
		
		public function setIsStandAlone(flag:Boolean):void {
			trace("WalkingVO.setIsStandAlone");
			this.isStandAlone = flag;
		}
		
		public function getUserVO():UserVO {
			return this.userVO;
		}
		
		/**
		 * 認証情報をセットし、グラフデータの取得を試みる。
		 */
		public function setUserVO(uVo:UserVO):void {
			trace("WalkingVO.setUserVO");
			this.userVO = uVo;
			makeWSSEToken();
			getWalkingGraph();
		}
		
		private function makeWSSEToken():void {
			trace("WalkingVO.makeWSSEToken");
			this.wsseToken = WSSEUsernameToken.getUsernameToken(userVO.userId, userVO.password);
		}
		
		
		public function getWalkingGraph():void {
			if(isStandAlone) {
				getWalkingGraphStandAlone();
			} else {
				getWalkingGraphHatena();
			}
		}
		
		public function getWalkingGraphStandAlone():void {
			succeededAuth = true;

			walkingData = walkingSO.data.walkingData as ArrayCollection;
			if(walkingData == null) {
				walkingData = new ArrayCollection();
			}
		}
		
		/**
		 * はてなからグラフ情報を取得を試みる
		 */
		public function getWalkingGraphHatena():void {
			trace("WalkingVO.getWalkingGraphHatena");
			var param:URLVariables = new URLVariables();
			param.graphname = WalkingVO.DB;
			param.type = "json";
			
			var request:URLRequest = new URLRequest(WalkingVO.URL_GRAPH_HATENA_API);
			request.method = URLRequestMethod.GET;
			request.requestHeaders = new Array(new URLRequestHeader("X-WSSE", wsseToken));
			request.data = param;

			var loader:URLLoader = new URLLoader(request);
			loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler, false, 0, true);
			loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true); 
			loader.load(request);
		}
		
		public function setWalkingData(d:Date, hosu:String):void {
			if(isStandAlone) {
				setWalkingDataStandAlone(d, hosu);
			} else {
				setWalkingDataHatena(d, hosu);
			}
		}
		
		public function setWalkingDataStandAlone(d:Date, hosu:String):void {
			walkingData.addItem(new DataVO(hatenaDateFormatter.format(d), hosu));
			walkingSO.setProperty("walkingData", walkingData);
		}
		
		public function setWalkingDataHatena(d:Date, hosu:String):void {
			trace("WalkingVO.setWalkingData");
			var param:URLVariables = new URLVariables();
			param.graphname = encodeURI(WalkingVO.DB);
			param.date = hatenaDateFormatter.format(d);
			param.value = hosu;
			
			var request:URLRequest = new URLRequest(WalkingVO.URL_GRAPH_HATENA_API);
			request.method = URLRequestMethod.POST;
			request.requestHeaders = new Array(new URLRequestHeader("X-WSSE", wsseToken));
			request.data = param;				

			var loader:URLLoader = new URLLoader();
			loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler, false, 0, true);
			loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true); 
			loader.load(request);
		}
		
		/**
		 * IOErrorを取得
		 */
		private function ioErrorHandler(event:IOErrorEvent):void {
			trace(event.errorID);
			trace(event.text);
			succeededAuth = false;
		}
		
		/**
		 * Httpのリターンコードに基づいて認証ができたかどうかを確認する。認証ができなかった場合は認証エラーとする。
		 */
		private function httpStatusHandler(event:HTTPStatusEvent):void {
			trace("WalkingVO.httpStatusHandler : " + event.status);

			var loader:URLLoader = event.target as URLLoader;

			succeededAuth = true;
			switch(event.status) {
				case 200:
					// 取得
					loader.addEventListener(Event.COMPLETE, selectCompleteHandler, false, 0, true);
					break;
				case 201:
					// 登録
					loader.addEventListener(Event.COMPLETE, updateCompleteHandler, false, 0, true);
					break;
				case 404:
					// データ無し
					walkingData = new ArrayCollection();
					break;
				default:
					// 認証エラー
					// succeededAuth = false;
					break;
			}
		}
		
		private function selectCompleteHandler(event:Event):void {
			trace("WalkingVO.selectCompleteHandler");
			var loader:URLLoader = event.currentTarget as URLLoader;
			
			walkingData = new ArrayCollection();

			if(loader.bytesLoaded >= 3) {
				var result:Object = JSON.decode(loader.data);

				for (var o:Object in result) {
					walkingData.addItem(new DataVO(o.toString(), result[o].toString().split(".")[0]));
				}
				
				var sort:Sort = new Sort();
				sort.fields = [new SortField("date", true)];
				walkingData.sort = sort;
				walkingData.refresh();
			}
		}
		
		private function updateCompleteHandler(event:Event):void {
			trace("WalkingVO.updateCompleteHandler");
			
			getWalkingGraph();
		}
		
		public function getHatenaGraphImageURLRequest(enemy:String = null):URLRequest {
			var urlString:String = URL_GRAPH_HATENA;

			if(enemy == null) {
				urlString = urlString + userVO.userId + "/graph?graphname=" + DB + "&mode=detail";
			} else {
				urlString = urlString + "/graph?mode=detail" + 
										"&id=" + userVO.userId + "&graphname=" + DB +
										"&id=" + enemy + "&graphname=" + DB +
										"&mode=detail";
			}
			var urlRequest:URLRequest = new URLRequest(urlString);
			urlRequest.useCache = false;
			
			return urlRequest;
		}

		public function getHatenaGraphURLRequest():URLRequest {
			var urlString:String = URL_GRAPH_HATENA + userVO.userId + "/" + DB + "/";
			var urlRequest:URLRequest = new URLRequest(urlString);
			urlRequest.useCache = false;
			
			return urlRequest;
		}
	}
}